home *** CD-ROM | disk | FTP | other *** search
/ Electronic Clipper 1995 April / Electronic Clipper 1995-04.iso / pc / pc_users / ideasrc / setup / pviewer / zoomctrl.c < prev   
Text File  |  1993-04-17  |  31KB  |  753 lines

  1.  
  2. // ---------------------------------------------------------------------
  3. //
  4. // ZoomCtrl.c - Picture Viewer - QuickTime for Windows
  5. //
  6. //              Version 1.0
  7. //
  8. //              (c) 1988-1992 Apple Computer, Inc. All Rights Reserved.
  9. //
  10. // ---------------------------------------------------------------------
  11.  
  12.  
  13. // Includes
  14. // --------
  15.    #define NOMINMAX
  16.    #include <Windows.H>               // Required by Windows
  17.    #include <stdlib.h>                // Required for abs function
  18.  
  19.    #include <qtole.h>                 // Interface to qtole dll
  20.    #include <qtw.h>                   // Interface to QuickTime
  21.                                       // Needed for struct defs in picture.h
  22.    #include "common.h"                // Interface to common.c
  23.  
  24.    #include "viewer.h"                // Interface to *.c files
  25.    #include "viewer.hr"               // Defines used in *.rc files
  26.    #include "picture.h"               // Interface to picture window
  27.                                       // child window processing
  28.  
  29. // Consts
  30. // ---------
  31.       // These are used instead of GetSysColors because user may change 
  32.       // system colors using control panel in which case, our colors would
  33.       // no longer match the Windows button colors which do not change
  34.    #define BTNFACECOLOR        (RGB( 192, 192, 192 ))
  35.    #define BTNSHADOWCOLOR      (RGB( 128, 128, 128 ))
  36.    #define BTNHIGHLIGHTCOLOR   (RGB( 255, 255, 255 ))
  37.  
  38.    #define TEXT_HEIGHT           7    // Text height in points 
  39.    #define TEXT_EXTRA_SPACING    2    // Extra spacing between characters in
  40.                                       // percent text
  41.  
  42.  
  43.      // This struct defines the bounds of the zones used by the zoom control
  44.    typedef struct                     // Hungarian notation: zns
  45.      {POINT      ptBuckle;         // position of UL corner of buckle
  46.                                    // in the corresponding zone
  47.       WORD       wZoomMultiplier;  // Zoom scaling multiplier
  48.       char       szPercent[8];     // percent text i.e. "150%   "
  49.                                    // This string is padded with with blanks
  50.      } ZONES, * NPZONES;
  51.  
  52. // Message-Persistent Data
  53. // -----------------------
  54.    static struct                       // Hungarian notation: g
  55.      {     // These bitmaps and dimensions are used in the zoom control
  56.            // They are shared by all instances
  57.       RECT        rcBar;               // Rect defining belt in control
  58.       RECT        rcYard;              // Rect defining area in which mouse
  59.                                        // dragging works. When the mouse is
  60.                                        // dragged outside this rect, the
  61.                                        // buckle does not follow
  62.       HBITMAP     hbmpActiveBuckle;    // Handle to active buckle bitmap
  63.       WORD        wBuckleWidth;        // Width of buckle bitmap
  64.       WORD        wBuckleHeight;       // Height of buckle bitmap
  65.       ZONES       znsZones[NUM_OF_ZOOMS];  // Array of zone structs
  66.       POINT       ptText;              // Upper-Left corner of % text
  67.       int         nTextHeight;         // % Text height
  68.       WORD        wWidthWnd;           // Adjusted window width after  
  69.                                        // correcting for font size
  70.     } g;
  71.  
  72.  
  73.  
  74. // Internal Function Declarations
  75. // ------------------------------
  76.    static LONG NEAR BuildBuckleStuff     (HWND);
  77.    static LONG NEAR UpdateBuckleAndText  (HWND, HDC, NPPICTUREDATA, WORD,
  78.                                                       HBITMAP, BOOL, BOOL);
  79.    static VOID NEAR Draw3DRect           (HDC, int, int, int, int);
  80.    static LONG NEAR DrawBuckle           (HDC, NPPICTUREDATA, NPZONES,
  81.                                                        HBITMAP, BOOL, BOOL);
  82.    static WORD NEAR PointToZoomIndex     (PPOINT, WORD);
  83.  
  84.  
  85. // Function: PictureZoomWndProc - Window proc for the picture resizing
  86. //                                scroll bar
  87. // --------------------------------------------------------------------
  88. // Parameters: As required by Microsoft Windows
  89. //
  90. // Returns:    Via DefWindowProc
  91. // --------------------------------------------------------------------
  92.    LONG __export CALLBACK PictureZoomWndProc
  93.              (HWND hwndZoom, UINT message, WPARAM wParam, LPARAM lParam)
  94.  
  95.      {     // These statics are only used during mouse capture
  96.       static BOOL     bDragging;       // Dragging flag
  97.       static WORD     wZoomIndex;      // Current zoom index during dragging
  98.  
  99.       NPPICTUREDATA   pPictureData;    // -> picture data struct
  100.       PAINTSTRUCT     ps;              // Paint struct
  101.       HDC             hdc;             // Control dc
  102.       RECT            rcZoom;          // Client rect of control
  103.       HWND            hwndPicture;     // Handle of picture window
  104.       HBRUSH          hbrush;          // Handle of brush
  105.       HBRUSH          hbrushSave;      // Handle of prev brush
  106.       NPZONES         pznsZone;        // -> zone struct
  107.       POINT           ptMouse;         // Mouse position
  108.       WORD            wNewZoomIndex;   // New zoom index
  109.       RECT            rcBuckle;        // Buckle rect
  110.  
  111.  
  112.       if( !(pPictureData = (NPPICTUREDATA)
  113.                 GetWindowWord( hwndPicture = GetParent( hwndZoom ), 0 )))
  114.           return DefWindowProc( hwndZoom, message, wParam, lParam);
  115.  
  116.       switch( message )
  117.          {case WM_CREATE:
  118.                  // Set statics: rcBar, zones and bitmaps for buckle
  119.                  // This data is shared by all instances
  120.               if( !g.hbmpActiveBuckle && BuildBuckleStuff( hwndZoom ))
  121.                   return -1L;
  122.  
  123.                  // Create a bitmap that will save the area under the buckle
  124.                  // Each instance gets one of these
  125.               if( !( hdc = GetDC( hwndZoom )))
  126.                  {CommonTellUser( ViewerQueryResources(),
  127.                        VIEWER_STRING_NODC, VIEWER_STRING_CAPTION, MB_OK );
  128.                   return 0L;
  129.                  }
  130.  
  131.               if( !(pPictureData->zsZoomScroll.hbmpNotBuckle =
  132.                           CreateCompatibleBitmap( hdc,
  133.                                       g.wBuckleWidth, g.wBuckleHeight )))
  134.                  {CommonTellUser( ViewerQueryResources(),
  135.                                    VIEWER_STRING_NOMEMORY, NULL, MB_OK );
  136.  
  137.                   ReleaseDC( hwndZoom, hdc );
  138.                   return -1L;
  139.                  }
  140.  
  141.               ReleaseDC( hwndZoom, hdc );
  142.               return 0L;
  143.  
  144.           case WM_KEYDOWN:
  145.               switch( wParam )
  146.                  {case VK_ADD:
  147.                   case VK_SUBTRACT:
  148.                       wZoomIndex =
  149.                              pPictureData->zsZoomScroll.wCurZoomIndex +
  150.                                             ((wParam == VK_ADD) ? 1 : -1);
  151.                       if( (wZoomIndex < IMAGE_SIZE_FIRST ) ||
  152.                            (wZoomIndex >= IMAGE_SIZE_FIRST + NUM_OF_ZOOMS))
  153.                           return 0L;
  154.  
  155.                       if( !(hdc = GetDC( hwndZoom )))
  156.                          {CommonTellUser( ViewerQueryResources(),
  157.                                        VIEWER_STRING_NODC,
  158.                                          VIEWER_STRING_CAPTION, MB_OK );
  159.                           return 0L;
  160.                          }
  161.  
  162.                       UpdateBuckleAndText( hwndZoom, hdc, pPictureData,
  163.                              wZoomIndex, g.hbmpActiveBuckle, FALSE, TRUE );
  164.                       ReleaseDC( hwndZoom, hdc );
  165.  
  166.                       ZoomPicture( hwndPicture, wZoomIndex );
  167.  
  168.                       return 0L;
  169.  
  170.                   default:
  171.                       break;
  172.                  }
  173.               break;
  174.  
  175.           case WM_LBUTTONDOWN:
  176.               ptMouse = MAKEPOINT( lParam );
  177.               if( !PtInRect( &g.rcBar, ptMouse ))
  178.                   return 0L;
  179.  
  180.               wZoomIndex = PointToZoomIndex( &ptMouse,
  181.                                  pPictureData->zsZoomScroll.wCurZoomIndex );
  182.  
  183.               if( wZoomIndex != pPictureData->zsZoomScroll.wCurZoomIndex )
  184.                  {if( !(hdc = GetDC( hwndZoom )))
  185.                      {CommonTellUser( ViewerQueryResources(),
  186.                                    VIEWER_STRING_NODC,
  187.                                             VIEWER_STRING_CAPTION, MB_OK );
  188.                       return 0L;
  189.                      }
  190.  
  191.                   UpdateBuckleAndText( hwndZoom, hdc, pPictureData,
  192.                              wZoomIndex, g.hbmpActiveBuckle, FALSE, TRUE );
  193.                   ReleaseDC( hwndZoom, hdc );
  194.                  }
  195.  
  196.               SetCapture( hwndZoom );
  197.               bDragging = TRUE;
  198.  
  199.               return 0L;
  200.  
  201.           case WM_LBUTTONUP:
  202.               if( bDragging )
  203.                  {ReleaseCapture();
  204.                   ZoomPicture( hwndPicture, wZoomIndex );
  205.                  }
  206.               bDragging = FALSE;
  207.               return 0L;
  208.  
  209.           case WM_MOUSEMOVE:
  210.               if( !bDragging )
  211.                   return 0L;
  212.  
  213.               ptMouse = MAKEPOINT( lParam );
  214.               if( PtInRect( &g.rcYard, ptMouse ))
  215.                  {if( wZoomIndex == ( wNewZoomIndex = 
  216.                                PointToZoomIndex( &ptMouse, wZoomIndex )))
  217.                       return 0L;
  218.                  }
  219.               else
  220.                  {wNewZoomIndex = pPictureData->zsZoomScroll.wCurZoomIndex;
  221.                  }
  222.  
  223.               wZoomIndex = wNewZoomIndex;
  224.  
  225.               if( !(hdc = GetDC( hwndZoom )))
  226.                  {CommonTellUser( ViewerQueryResources(),
  227.                        VIEWER_STRING_NODC, VIEWER_STRING_CAPTION, MB_OK );
  228.                   return 0L;
  229.                  }
  230.  
  231.               UpdateBuckleAndText( hwndZoom, hdc, pPictureData, wZoomIndex,
  232.                                          g.hbmpActiveBuckle, FALSE, TRUE );
  233.               ReleaseDC( hwndZoom, hdc );
  234.  
  235.               return 0L;
  236.  
  237.     // WM_USER messages
  238.  
  239.           case WM_ZOOM_MOVEBUCKLE:
  240.               if( !(hdc = GetDC( hwndZoom )))
  241.                  {CommonTellUser( ViewerQueryResources(),
  242.                        VIEWER_STRING_NODC, VIEWER_STRING_CAPTION, MB_OK );
  243.                   return 0L;
  244.                  }
  245.  
  246.               UpdateBuckleAndText( hwndZoom, hdc, pPictureData,
  247.                         pPictureData->zsZoomScroll.wCurZoomIndex,
  248.                                      g.hbmpActiveBuckle, FALSE, TRUE );
  249.               ReleaseDC( hwndZoom, hdc );
  250.               return 0L;
  251.  
  252.     // End WM_USER messages
  253.  
  254.           case WM_PAINT:
  255.               pznsZone = g.znsZones +
  256.                              pPictureData->zsZoomScroll.wCurZoomIndex -
  257.                                                           IMAGE_SIZE_FIRST;
  258.  
  259.                  // Force repaint of the buckle to prevent the
  260.                  // repainting logic from getting off
  261.               *((LPPOINT) &rcBuckle.left) = 
  262.                                     pPictureData->zsZoomScroll.ptBucklePos;
  263.               rcBuckle.right  = rcBuckle.left + g.wBuckleWidth;
  264.               rcBuckle.bottom = rcBuckle.top  + g.wBuckleHeight;
  265.               InvalidateRect( hwndZoom, &rcBuckle, TRUE );
  266.  
  267.               if( !BeginPaint( hwndZoom, &ps ))
  268.                   return 0L;
  269.  
  270.               GetClientRect( hwndZoom, &rcZoom );
  271.  
  272.                  // Draw the main rect
  273.               if( !( hbrush = CreateSolidBrush( BTNFACECOLOR )))
  274.                  {EndPaint( hwndZoom, &ps );
  275.                   return 0L;
  276.                  }
  277.               FillRect( ps.hdc, &rcZoom, hbrush );
  278.               DeleteObject( hbrush );
  279.  
  280.                  // Draw the belt
  281.               if( !( hbrush = CreateSolidBrush( BTNSHADOWCOLOR )))
  282.                  {EndPaint( hwndZoom, &ps );
  283.                   return 0L;
  284.                  }
  285.               hbrushSave = SelectObject( ps.hdc, hbrush );
  286.               Rectangle( ps.hdc, g.rcBar.left, g.rcBar.top,
  287.                                             g.rcBar.right, g.rcBar.bottom );
  288.               DeleteObject( SelectObject( ps.hdc, hbrushSave ));
  289.  
  290.                  // Draw the buckle
  291.               UpdateBuckleAndText( hwndZoom, ps.hdc, pPictureData,
  292.                                pPictureData->zsZoomScroll.wCurZoomIndex,
  293.                                          g.hbmpActiveBuckle, TRUE, TRUE );
  294.  
  295.               EndPaint( hwndZoom, &ps );
  296.  
  297.               return 0L;
  298.  
  299.           case WM_DESTROY:
  300.                 // Each instance has one of these
  301.               if( pPictureData->zsZoomScroll.hbmpNotBuckle )
  302.                  {DeleteObject( pPictureData->zsZoomScroll.hbmpNotBuckle );
  303.                   pPictureData->zsZoomScroll.hbmpNotBuckle = NULL;
  304.                  }
  305.  
  306.                 // All instances share these
  307.               if( ViewerQueryNumPictures() <= 1 )
  308.                  {if( g.hbmpActiveBuckle )
  309.                      DeleteObject( g.hbmpActiveBuckle );
  310.                   g.hbmpActiveBuckle   = NULL;
  311.                  }
  312.  
  313.               pPictureData->zsZoomScroll.hwnd = NULL;
  314.  
  315.               return 0L;
  316.  
  317.           default:
  318.               break;
  319.          }
  320.  
  321.       return DefWindowProc( hwndZoom, message, wParam, lParam);
  322.  
  323.      }
  324.  
  325.  
  326. // Function: UpdateBuckleAndText - Draws the buckle and text
  327. // --------------------------------------------------------------------
  328. // Parameters: HWND           hwndZoom          Window handle of control
  329. //             HDC            hdc               DC of control
  330. //             NPPICTUREDATA  pPictureData      -> picture data struct
  331. //             WORD           wZoomIndex        Current zoom index
  332. //             HBITMAP        hbmpBuckle        Handle of buckle bitmap
  333. //             BOOL           bRepainting       Repainting flag
  334. //             BOOL           bUpdateNoBuckle   Update no buckle bitmap flag
  335. //
  336. // Returns:    LONG             0L if OK
  337. // --------------------------------------------------------------------
  338.    static LONG NEAR UpdateBuckleAndText( HWND hwndZoom,
  339.                       HDC hdc, NPPICTUREDATA pPictureData,
  340.                             WORD wZoomIndex, HBITMAP hbmpBuckle,
  341.                                    BOOL bRepainting, BOOL bUpdateNoBuckle )
  342.  
  343.      {NPZONES    pznsZone;        // -> zone struct
  344.       HFONT      hFont;           // Handle to font used for % text
  345.       HFONT      hsaveFont;       // Prev font
  346.       COLORREF   dwcrSave;        // Prev color
  347.       UINT       uSaveAlign;      // Prev text alignment
  348.  
  349.  
  350.       pznsZone = g.znsZones + wZoomIndex - IMAGE_SIZE_FIRST;
  351.  
  352.          // Draw the buckle in the new position
  353.       if( DrawBuckle(hdc, pPictureData, pznsZone, hbmpBuckle,
  354.                                           bRepainting, bUpdateNoBuckle ))
  355.           return 0L;
  356.  
  357.          // Get the font. Don't bother with error message. If this
  358.          // fails, the system font will be used
  359.       if( hFont = MakeAnArialFont( hdc, g.nTextHeight ))
  360.           hsaveFont = SelectObject( hdc, hFont );
  361.  
  362.       SetTextCharacterExtra( hdc, 
  363.                    GetTextCharacterExtra( hdc ) + TEXT_EXTRA_SPACING );
  364.  
  365.       dwcrSave = SetBkColor( hdc, BTNFACECOLOR );
  366.  
  367.          // Draw the % text
  368.       uSaveAlign = SetTextAlign( hdc, TA_LEFT | TA_BASELINE );
  369.       TextOut( hdc, g.ptText.x, g.ptText.y, pznsZone->szPercent,
  370.                                            lstrlen( pznsZone->szPercent ));
  371.       SetTextAlign( hdc, uSaveAlign );
  372.  
  373.       if( hFont )
  374.           DeleteObject( SelectObject( hdc, hsaveFont ));
  375.       SetBkColor( hdc, dwcrSave );
  376.  
  377.       return 0L;
  378.      }
  379.  
  380.  
  381. // Function: DrawBuckle - Draws the buckle
  382. // --------------------------------------------------------------------
  383. // Parameters: HDC              hdc              hdc of control
  384. //             NPPICTUREDATA    pPictureData     -> to picturedata struct
  385. //             NPZONES          pznsZone         -> zone struct. Contains
  386. //                                               offsets used to position buckle
  387. //             HBITMAP          hbmpBuckle       Buckle bitmap
  388. //             BOOL             bRepainting      TRUE if WM_PAINT message
  389. //             BOOL             bUpdateNoBuckle  TRUE if area under buckle
  390. //                                               should be saved. This is
  391. //                                               false if only changing
  392. //                                               activation state of buckle
  393. //
  394. // Returns:    LONG             0L if OK
  395. // --------------------------------------------------------------------
  396.    static LONG NEAR DrawBuckle( HDC hdc, NPPICTUREDATA pPictureData,
  397.                             NPZONES pznsZone, HBITMAP hbmpBuckle,
  398.                                     BOOL bRepainting, BOOL bUpdateNoBuckle )
  399.  
  400.      {HDC           hdcMem;      // Memory device context
  401.       HBITMAP       hbmpSave;    // Prev bitmap
  402.  
  403.  
  404.       if( !(hdcMem = CreateCompatibleDC( hdc )))
  405.          {CommonTellUser( ViewerQueryResources(),
  406.                        VIEWER_STRING_NODC, VIEWER_STRING_CAPTION, MB_OK );
  407.           return VIEWER_STRING_NODC;
  408.          }
  409.  
  410.       hbmpSave = SelectObject( hdcMem,
  411.                                pPictureData->zsZoomScroll.hbmpNotBuckle );
  412.          // Use no buckle bitmap to remove buckle
  413.       if( !bRepainting )
  414.          {BitBlt( hdc, pPictureData->zsZoomScroll.ptBucklePos.x,
  415.                        pPictureData->zsZoomScroll.ptBucklePos.y,
  416.                        g.wBuckleWidth, g.wBuckleHeight,
  417.                        hdcMem, 0, 0, SRCCOPY );
  418.          }
  419.  
  420.          // Save area under new position of buckle
  421.       if( bUpdateNoBuckle )
  422.          {BitBlt( hdcMem, 0, 0, g.wBuckleWidth, g.wBuckleHeight,
  423.                 hdc, pznsZone->ptBuckle.x, pznsZone->ptBuckle.y, SRCCOPY );
  424.           pPictureData->zsZoomScroll.ptBucklePos = pznsZone->ptBuckle;
  425.          }
  426.  
  427.          // Draw buckle
  428.       SelectObject( hdcMem, hbmpBuckle );
  429.       BitBlt( hdc, pznsZone->ptBuckle.x, pznsZone->ptBuckle.y,
  430.                    g.wBuckleWidth, g.wBuckleHeight, hdcMem, 0, 0, SRCCOPY );
  431.  
  432.       SelectObject( hdcMem, hbmpSave );
  433.       DeleteDC( hdcMem );
  434.  
  435.       return 0L;
  436.      }
  437.  
  438.  
  439. // Function: BuildBuckleStuff - processes WM_CREATE message for
  440. //                              zoom wnd control
  441. // --------------------------------------------------------------------
  442. // Parameters: HWND         hwndZoom       Window handle of zoom control
  443. //
  444. // Returns:    LONG         0L if OK
  445. // --------------------------------------------------------------------
  446.    static LONG NEAR BuildBuckleStuff( HWND hwndZoom )
  447.  
  448.      {RECT     rcClient;         // Client rect of window
  449.       POINT    ptBuckle;         // Temp UL corner of buckle
  450.       WORD     wBar;             // Length of bar
  451.       WORD     wBar1;            // Temp length of bar
  452.       WORD     wBar2;            // Temp length of bar
  453.       WORD     wBuckleP1;        // Width of buckle + 1 pixel
  454.       HDC      hdc;              // Device context of control
  455.       HDC      hdcMem;           // Memory dc
  456.       HBITMAP  hbmpSave;         // Prev bitmap
  457.       char     szFormat[6];      // Resource string format for % text
  458.       int      i;                // Temp index
  459.       int      j;                // Temp index
  460.       WORD     wBarHeight;       // Bar height
  461.       WORD     wBuckleExtension; // Half the amount by which buckle height exceeds
  462.                                  // bar height
  463.       WORD     wMaxTextExtent;   // Max text extent of % text
  464.       WORD     wTextExtent;      // Text extent of % text
  465.       HFONT    hFont;            // Font used to display % text
  466.       HFONT    hsaveFont;        // Prev font
  467.       TEXTMETRIC tm;             // Text metrics struct
  468.       BOOL     bGotTextMetrics;  // TRUE if GetTextMetrics worked 
  469.       WORD     wAveChar;         // Average width of % text char
  470.       int      nMaxTextHeight;   // Max text height
  471.  
  472.  
  473.       static WORD wZoomMults[NUM_OF_ZOOMS] =     // Array of zoom multipliers
  474.             { 25, 50, 75, 100, 150, 200, 400 };  // that define the scaling
  475.  
  476.  
  477.       GetClientRect( hwndZoom, &rcClient );
  478.  
  479.          // rcYard defines the area within which the control responds to
  480.          // mouse dragging
  481.       g.rcYard = rcClient;
  482.       g.rcYard.left   -= (WORD) GetSystemMetrics( SM_CXVSCROLL );
  483.       g.rcYard.right  += (WORD) GetSystemMetrics( SM_CXVSCROLL );
  484.       g.rcYard.top    -= (WORD) GetSystemMetrics( SM_CYHSCROLL );
  485.       g.rcYard.bottom += (WORD) GetSystemMetrics( SM_CYHSCROLL );
  486.  
  487.          // Set rect for slider bar
  488.       g.rcBar.left   = rcClient.bottom / 3;
  489.       g.rcBar.right  = g.rcBar.left + (65 * rcClient.right / 100 );
  490.       g.rcBar.top    = max( 3 * rcClient.bottom / 10, 3 );
  491.       g.rcBar.bottom = rcClient.bottom - g.rcBar.top;
  492.       wBar = g.rcBar.right - g.rcBar.left;
  493.       wBarHeight = g.rcBar.bottom - g.rcBar.top;
  494.  
  495.       wBuckleExtension = ( rcClient.bottom - wBarHeight - 2 ) / 2;
  496.       if( wBuckleExtension > 2 )
  497.           wBuckleExtension = 2;
  498.       g.wBuckleHeight = wBarHeight + 2 * wBuckleExtension;
  499.  
  500.          // Set buckle width and then adjust bar or buckle length so that
  501.          // bar length is integral number of buckles long + 2 pixels
  502.  
  503.       g.wBuckleWidth = ( wBar - NUM_OF_ZOOMS - 1 ) / NUM_OF_ZOOMS;
  504.       wBar1 = ( g.wBuckleWidth + 1 ) * NUM_OF_ZOOMS + 1;
  505.       wBar2 = ( (g.wBuckleWidth + 1) + 1 ) * NUM_OF_ZOOMS + 1;
  506.       if( abs( wBar - wBar1 ) >= abs( wBar - wBar2 ))
  507.          {g.wBuckleWidth += 1;
  508.           g.rcBar.right = g.rcBar.left + wBar2;
  509.          }
  510.       else
  511.          {g.rcBar.right = g.rcBar.left + wBar1;
  512.          }
  513.  
  514.    
  515.       if( !(hdc = GetDC( hwndZoom )))
  516.          {CommonTellUser( ViewerQueryResources(),
  517.                        VIEWER_STRING_NODC, VIEWER_STRING_CAPTION, MB_OK );
  518.           return VIEWER_STRING_NODC;
  519.          }
  520.  
  521.    // Set zones
  522.         // Initialize text strings
  523.       LoadString( ViewerQueryResources(), VIEWER_STRING_PERCENT,
  524.                                              szFormat, sizeof( szFormat ));
  525.       wMaxTextExtent = 0;
  526.          // Set text height
  527.       g.nTextHeight = -MulDiv( TEXT_HEIGHT,
  528.                              GetDeviceCaps( hdc, LOGPIXELSY ), 72 );
  529.          // Limit text height to 2/3 of the window height
  530.       nMaxTextHeight = -MulDiv( 2, rcClient.bottom, 3 );
  531.          // use max because values are < 0
  532.       g.nTextHeight = max( g.nTextHeight, nMaxTextHeight );
  533.  
  534.          // Select font into dc so GetTextExtent will work
  535.       if( hFont = MakeAnArialFont( hdc, g.nTextHeight ))
  536.           hsaveFont = SelectObject( hdc, hFont );
  537.  
  538.       SetTextCharacterExtra( hdc, 
  539.                    GetTextCharacterExtra( hdc ) + TEXT_EXTRA_SPACING );
  540.  
  541.       for( i=0; i < NUM_OF_ZOOMS; i++ )
  542.          {   // Save multipliers for Query function
  543.           g.znsZones[i].wZoomMultiplier = wZoomMults[i]; 
  544.           wsprintf( g.znsZones[i].szPercent, szFormat,
  545.                                            g.znsZones[i].wZoomMultiplier );
  546.               // Get text extent before padding with blanks
  547.           wTextExtent = LOWORD( GetTextExtent( hdc, g.znsZones[i].szPercent, 
  548.                                       lstrlen( g.znsZones[i].szPercent )));
  549.           if( wMaxTextExtent < wTextExtent )
  550.              {wMaxTextExtent = wTextExtent;
  551.               wAveChar = wMaxTextExtent / lstrlen( g.znsZones[i].szPercent );
  552.              }
  553.  
  554.              // Now pad with blanks to erase previous text
  555.           for(j=lstrlen( g.znsZones[i].szPercent );
  556.                       j < sizeof( g.znsZones[i].szPercent ) - 1; j++ )
  557.               g.znsZones[i].szPercent[j] = ' ';
  558.           g.znsZones[i].szPercent[j] = '\0';
  559.          }
  560.  
  561.       bGotTextMetrics = GetTextMetrics( hdc, &tm );
  562.  
  563.       if( hFont )
  564.           DeleteObject( SelectObject( hdc, hsaveFont ));
  565.  
  566.         // Initialize buckle positions and zone edges
  567.       wBuckleP1  = g.wBuckleWidth + 1;
  568.       ptBuckle.x = g.rcBar.left + 1;
  569.       ptBuckle.y = g.rcBar.top - wBuckleExtension;
  570.       for( i=0; i < NUM_OF_ZOOMS; i++ )
  571.          {g.znsZones[i].ptBuckle = ptBuckle;
  572.           ptBuckle.x += wBuckleP1;
  573.          }
  574.  
  575.       if( !(hdcMem = CreateCompatibleDC( hdc )))
  576.          {ReleaseDC( hwndZoom, hdc );
  577.           CommonTellUser( ViewerQueryResources(),
  578.                    VIEWER_STRING_NODC, VIEWER_STRING_CAPTION, MB_OK );
  579.           return VIEWER_STRING_NODC;
  580.          }
  581.  
  582.          // build buckle
  583.       if( !( g.hbmpActiveBuckle = CreateCompatibleBitmap
  584.                             ( hdc, g.wBuckleWidth, g.wBuckleHeight )))
  585.          {DeleteDC( hdcMem );
  586.           ReleaseDC( hwndZoom, hdc );
  587.           CommonTellUser( ViewerQueryResources(),
  588.                                    VIEWER_STRING_NOMEMORY, NULL, MB_OK );
  589.           return VIEWER_STRING_NOMEMORY;
  590.          }
  591.  
  592.       hbmpSave = SelectObject( hdcMem, g.hbmpActiveBuckle );
  593.  
  594.       Draw3DRect( hdcMem, 0, 0, g.wBuckleWidth, g.wBuckleHeight );
  595.  
  596.       SelectObject( hdcMem,  hbmpSave );
  597.       DeleteDC( hdcMem );
  598.  
  599.          // Set reference point for TextOut
  600.       g.ptText.x = g.rcBar.right + 4;
  601.       if( bGotTextMetrics )
  602.          {g.ptText.y = max( g.rcBar.bottom, 
  603.                 ( rcClient.bottom +
  604.                             tm.tmAscent - tm.tmInternalLeading ) / 2 );
  605.          }
  606.       else
  607.          {g.ptText.y = g.rcBar.bottom;
  608.          }
  609.  
  610.          // Now make sure text will fit in window, adjust width if it doesn't
  611.       g.wWidthWnd = g.ptText.x + wMaxTextExtent + ( 3 * wAveChar / 2 );
  612.  
  613.       ReleaseDC( hwndZoom, hdc );
  614.  
  615.       return 0L;
  616.      }
  617.  
  618. // Function: Draw3DRect - Draws the 3D stuff on a given rect
  619. // --------------------------------------------------------------------
  620. // Parameters: HDC              hdc          Device context
  621. //             int              left         Rect.left
  622. //             int              top          Rect.top
  623. //             int              right        Rect.right
  624. //             int              bottom       Rect.bottom
  625. //
  626. // Returns:    VOID
  627. // --------------------------------------------------------------------
  628.    static VOID NEAR Draw3DRect( HDC hdc,
  629.                            int nleft, int ntop, int nright, int nbottom )
  630.  
  631.      {HPEN     hpenSave;            // Prev pen
  632.       HPEN     hpenHighLite;        // HighLite pen
  633.       HPEN     hpenShadow;          // Shadow pen
  634.       HBRUSH   hbrush;              // Brush
  635.       HBRUSH   hbrushSave;          // Prev brush
  636.  
  637.  
  638.    // Don't bother with error messages. Failure here will not cause a
  639.    // crash. The rects just won't look right.
  640.  
  641.       if( hbrush = CreateSolidBrush( BTNFACECOLOR ))
  642.          {hbrushSave = SelectObject( hdc, hbrush );
  643.           Rectangle( hdc, nleft, ntop, nright, nbottom );
  644.           DeleteObject( SelectObject( hdc, hbrushSave ));
  645.          }
  646.  
  647.       if( hpenShadow = CreatePen( PS_SOLID, 1, BTNSHADOWCOLOR))
  648.          {hpenSave = SelectObject( hdc, hpenShadow );
  649.           MoveTo( hdc, nright - 2, 1 );
  650.           LineTo( hdc, nright - 2, nbottom - 2 );
  651.           LineTo( hdc, 0, nbottom - 2);
  652.           DeleteObject( SelectObject( hdc, hpenSave ));
  653.          }
  654.  
  655.       if( hpenHighLite = CreatePen( PS_SOLID, 1, BTNHIGHLIGHTCOLOR ))
  656.          {hpenSave = SelectObject( hdc, hpenHighLite );
  657.           MoveTo( hdc, 1, nbottom - 3 );
  658.           LineTo( hdc, 1, 1 );
  659.           LineTo( hdc, nright - 2, 1 );
  660.           DeleteObject( SelectObject( hdc, hpenSave ));
  661.          }
  662.  
  663.       return;
  664.      }
  665.  
  666.  
  667. // Function: PointToZoomIndex - Finds index of zoon cooresponding to mouse
  668. //                              position
  669. // --------------------------------------------------------------------
  670. // Parameters: PPOINT       pptMouse         -> current mouse position
  671. //             WORD         wCurZoneIndex    Current zone index
  672. //
  673. // Returns:    WORD         wZoomIndex
  674. // --------------------------------------------------------------------
  675.    static WORD NEAR PointToZoomIndex( PPOINT pptMouse, WORD wCurZoneIndex )
  676.  
  677.      {int        nxPos;          // Horizontal position of mouse
  678.       WORD       iCur;           // Current zone -> offset
  679.       WORD       i;              // Counter
  680.       int        nWidthP1;       // Width of buckle + 1 pixel
  681.  
  682.       nxPos = pptMouse->x;
  683.       nWidthP1 = g.wBuckleWidth + 1;
  684.       iCur = wCurZoneIndex - IMAGE_SIZE_FIRST;
  685.  
  686.          // Check if left of first zone
  687.       if( nxPos <= g.znsZones[0].ptBuckle.x + nWidthP1)
  688.           return IMAGE_SIZE_FIRST;
  689.  
  690.          // Check if in current zone
  691.       if( ( nxPos >= g.znsZones[iCur].ptBuckle.x - 1 ) &&
  692.                    ( nxPos <= g.znsZones[iCur].ptBuckle.x + nWidthP1 ))
  693.           return wCurZoneIndex;
  694.  
  695.          // Check rest of zones
  696.       for(i=0; i < NUM_OF_ZOOMS; i++ )
  697.          {if(( i != iCur ) &&
  698.                            ( nxPos <= g.znsZones[i].ptBuckle.x + nWidthP1 ))
  699.             return ( i + IMAGE_SIZE_FIRST );
  700.          }
  701.  
  702.       return ( IMAGE_SIZE_FIRST + NUM_OF_ZOOMS - 1 );
  703.      }
  704.  
  705.  
  706. //  The remaining functions are the query functions called by other modules
  707.  
  708. // Function: ViewerQueryZoomMultiplier - Query the zoom multiplier for the
  709. //                                       current zoom index
  710. // --------------------------------------------------------------------
  711. // Parameters: WORD           wZoomIndex    Current zoom index
  712. //
  713. // Returns:    WORD           wZoomMult     Corresponding zoom muliplier
  714. // --------------------------------------------------------------------
  715.    WORD FAR ViewerQueryZoomMultiplier( WORD wZoomIndex )
  716.  
  717.      {return g.znsZones[wZoomIndex - IMAGE_SIZE_FIRST].wZoomMultiplier;
  718.      }
  719.  
  720.  
  721. // Function: ViewerQueryZoomIndex - Query the zoom index for the
  722. //                                  current zoom multiplier 
  723. // --------------------------------------------------------------------
  724. // Parameters: WORD           wZoomMult     Current zoom muliplier
  725. //
  726. // Returns:    WORD           wZoomIndex    Corresponding zoom index
  727. // --------------------------------------------------------------------
  728.    WORD FAR ViewerQueryZoomIndex( WORD wZoomMultiplier )
  729.  
  730.      {int      i;
  731.  
  732.       for( i=0; i < NUM_OF_ZOOMS - 1; i++ )
  733.          {if( wZoomMultiplier <= g.znsZones[i].wZoomMultiplier )
  734.              break;
  735.          }
  736.  
  737.       return ( i + IMAGE_SIZE_FIRST );
  738.      }
  739.  
  740.  
  741. // Function: ViewerQueryZoomWndWidth - Query the final width of the 
  742. //                                     zoom window after adjustment for
  743. //                                     font (see BuildBuckleStuff())
  744. // --------------------------------------------------------------------
  745. // Parameters: VOID
  746. //
  747. // Returns:    WORD    wWidthWnd     final width of control
  748. // --------------------------------------------------------------------
  749.    WORD FAR ViewerQueryZoomWndWidth( VOID )
  750.  
  751.      {return g.wWidthWnd;
  752.      }
  753.